查看原文
其他

Android 10.0系统启动之Zygote进程(三)-「Android取经之路」

IngresGe IngresGe 2021-11-05

前几节已经讲完了Android10.0的Init启动过程以及Zygote架构。

Android取经之路——启动篇

Android系统架构-[Android取经之路]

Android是怎么启动的-[Android取经之路]

Android系统启动之init进程(一)-「Android取经之路」

Android系统启动之init进程(二)-「Android取经之路」

Android 10.0系统启动之init进程(三)-「Android取经之路」

Android 10.0系统启动之init进程(四)-「Android取经之路」

Android 10.0系统启动之Zygote进程(一)-「Android取经之路」

Android 10.0系统启动之Zygote进程(二)-「Android取经之路」

Android 10.0系统启动之Zygote进程(二)-「Android取经之路」


本节主要分析Zygote进程在JAVA世界的启动源码


4.2 Java世界的Zygote启动主要代码调用流程:

上节我们通过JNI调用ZygoteInit的main函数后,Zygote便进入了Java框架层,此前没有任何代码进入过Java框架层,换句换说Zygote开创了Java框架层。

4.2.1 [ZygoteInit.java]main.cpp

path:frameworks\base\core\java\com\android\internal\os\ZygoteInit.java

main的主要工作:

1.调用preload()来预加载类和资源

2.调用ZygoteServer()创建两个Server端的Socket--/dev/socket/zygote 和 /dev/socket/zygote_secondary,Socket用来等待ActivityManagerService来请求Zygote来创建新的应用程序进程。

3.调用forkSystemServer 来启动SystemServer进程,这样系统的关键服务也会由SystemServer进程启动起来。

4.最后调用runSelectLoop函数来等待客户端请求

后面我们主要来分析这四件事。

public static void main(String argv[]) { // 1.创建ZygoteServer ZygoteServer zygoteServer = null; // 调用native函数,确保当前没有其它线程在运行 ZygoteHooks.startZygoteNoThreadCreation(); //设置pid为0,Zygote进入自己的进程组 Os.setpgid(0, 0); ...... Runnable caller; try { ...... //得到systrace的监控TAG String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing"; TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag, Trace.TRACE_TAG_DALVIK); //通过systradce来追踪 函数ZygoteInit, 可以通过systrace工具来进行分析 //traceBegin 和 traceEnd 要成对出现,而且需要使用同一个tag bootTimingsTraceLog.traceBegin("ZygoteInit"); //开启DDMS(Dalvik Debug Monitor Service)功能 //注册所有已知的Java VM的处理块的监听器。线程监听、内存监听、native 堆内存监听、debug模式监听等等 RuntimeInit.enableDdms(); boolean startSystemServer = false; String zygoteSocketName = "zygote"; String abiList = null; boolean enableLazyPreload = false; //2. 解析app_main.cpp - start()传入的参数 for (int i = 1; i < argv.length; i++) { if ("start-system-server".equals(argv[i])) { startSystemServer = true; //启动zygote时,才会传入参数:start-system-server } else if ("--enable-lazy-preload".equals(argv[i])) { enableLazyPreload = true; //启动zygote_secondary时,才会传入参数:enable-lazy-preload } else if (argv[i].startsWith(ABI_LIST_ARG)) { //通过属性ro.product.cpu.abilist64\ro.product.cpu.abilist32 从C空间传来的值 abiList = argv[i].substring(ABI_LIST_ARG.length()); } else if (argv[i].startsWith(SOCKET_NAME_ARG)) { zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length()); //会有两种值:zygote和zygote_secondary } else { throw new RuntimeException("Unknown command line argument: " + argv[i]); } }
 // 根据传入socket name来决定是创建socket还是zygote_secondary final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME); // 在第一次zygote启动时,enableLazyPreload为false,执行preload if (!enableLazyPreload) { //systrace 追踪 ZygotePreload bootTimingsTraceLog.traceBegin("ZygotePreload"); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis());
 // 3.加载进程的资源和类,参考[4.2.2] preload(bootTimingsTraceLog); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); //systrae结束 ZygotePreload的追踪 bootTimingsTraceLog.traceEnd(); // ZygotePreload } else { // 延迟预加载, 变更Zygote进程优先级为NORMAL级别,第一次fork时才会preload Zygote.resetNicePriority(); }
 //结束ZygoteInit的systrace追踪 bootTimingsTraceLog.traceEnd(); // ZygoteInit //禁用systrace追踪,以便fork的进程不会从zygote继承过时的跟踪标记 Trace.setTracingEnabled(false, 0); // 4.调用ZygoteServer 构造函数,创建socket,会根据传入的参数, // 创建两个socket:/dev/socket/zygote 和 /dev/socket/zygote_secondary //参考[4.2.3] zygoteServer = new ZygoteServer(isPrimaryZygote); if (startSystemServer) { //5. fork出system server,参考[4.2.4] Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer); // 启动SystemServer if (r != null) { r.run(); return; } }
 // 6. zygote进程进入无限循环,处理请求 caller = zygoteServer.runSelectLoop(abiList); } catch (Throwable ex) { Log.e(TAG, "System zygote died with exception", ex); throw ex; } finally { if (zygoteServer != null) { zygoteServer.closeServerSocket(); } }
 // 7.在子进程中退出了选择循环。继续执行命令 if (caller != null) {  caller.run(); } }

日志:

01-10 11:20:32.219 722 722 D Zygote : begin preload01-10 11:20:32.219 722 722 I Zygote : Calling ZygoteHooks.beginPreload()01-10 11:20:32.249 722 722 I Zygote : Preloading classes...01-10 11:20:33.179 722 722 I Zygote : ...preloaded 7587 classes in 926ms.01-10 11:20:33.449 722 722 I Zygote : Preloading resources...01-10 11:20:33.459 722 722 I Zygote : ...preloaded 64 resources in 17ms.01-10 11:20:33.519 722 722 I Zygote : Preloading shared libraries...01-10 11:20:33.539 722 722 I Zygote : Called ZygoteHooks.endPreload()01-10 11:20:33.539 722 722 I Zygote : Installed AndroidKeyStoreProvider in 1ms.01-10 11:20:33.549 722 722 I Zygote : Warmed up JCA providers in 11ms.01-10 11:20:33.549 722 722 D Zygote : end preload01-10 11:20:33.649 722 722 D Zygote : Forked child process 160701-10 11:20:33.649 722 722 I Zygote : System server process 1607 has been created01-10 11:20:33.649 722 722 I Zygote : Accepting command socket connections10-15 06:11:07.749 722 722 D Zygote : Forked child process 298210-15 06:11:07.789 722 722 D Zygote : Forked child process 3004

4.2.2 [ZygoteInit.java] preload()

static void preload(TimingsTraceLog bootTimingsTraceLog) { Log.d(TAG, "begin preload");· }

什么是预加载:

预加载是指在zygote进程启动的时候就加载,这样系统只在zygote执行一次加载操作,所有APP用到该资源不需要再重新加载,减少资源加载时间,加快了应用启动速度,一般情况下,系统中App共享的资源会被列为预加载资源。

zygote fork子进程时,根据fork的copy-on-write机制可知,有些类如果不做改变,甚至都不用复制,子进程可以和父进程共享这部分数据,从而省去不少内存的占用。

预加载的原理:

zygote进程启动后将资源读取出来,保存到Resources一个全局静态变量中,下次读取系统资源的时候优先从静态变量中查找。

frameworks/base/config/preloaded-classes:

参考:

相关日志:

01-10 11:20:32.219 722 722 D Zygote : begin preload01-10 11:20:32.219 722 722 I Zygote : Calling ZygoteHooks.beginPreload()01-10 11:20:32.249 722 722 I Zygote : Preloading classes...01-10 11:20:33.179 722 722 I Zygote : ...preloaded 7587 classes in 926ms.01-10 11:20:33.539 722 722 I Zygote : Called ZygoteHooks.endPreload()01-10 11:20:33.549 722 722 D Zygote : end preload

4.2.3 [ZygoteServer.java] ZygoteServer()

path: frameworks\base\core\java\com\android\internal\os\ZygoteServer.java

作用:ZygoteServer 构造函数初始化时,根据传入的参数,利用LocalServerSocket 创建了4个本地服务端的socket,用来建立连接,

分别是:zygote、usap_pool_primary、zygote_secondary、usap_pool_secondary

private LocalServerSocket mZygoteSocket; private LocalServerSocket mUsapPoolSocket;
//创建zygote的socket ZygoteServer(boolean isPrimaryZygote) { mUsapPoolEventFD = Zygote.getUsapPoolEventFD(); if (isPrimaryZygote) { //创建socket,并获取socket对象,socketname:zygote mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME); //创建socket,并获取socket对象,socketname:usap_pool_primary mUsapPoolSocket = Zygote.createManagedSocketFromInitSocket( Zygote.USAP_POOL_PRIMARY_SOCKET_NAME); } else { //创建socket,并获取socket对象,socketname:zygote_secondary
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME); //创建socket,并获取socket对象,socketname:usap_pool_secondary mUsapPoolSocket = Zygote.createManagedSocketFromInitSocket( Zygote.USAP_POOL_SECONDARY_SOCKET_NAME); }
fetchUsapPoolPolicyProps(); mUsapPoolSupported = true; }

static LocalServerSocket createManagedSocketFromInitSocket(String socketName) { int fileDesc; // ANDROID_SOCKET_PREFIX为"ANDROID_SOCKET_" //加入传入参数为zygote,则fullSocketName:ANDROID_SOCKET_zygote final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; try { //init.zygote64_32.rc启动时,指定了4个socket: //分别是zygote、usap_pool_primary、zygote_secondary、usap_pool_secondary // 在进程被创建时,就会创建对应的文件描述符,并加入到环境变量中 // 这里取出对应的环境变量 String env = System.getenv(fullSocketName); fileDesc = Integer.parseInt(env); } catch (RuntimeException ex) { throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex); }
try { FileDescriptor fd = new FileDescriptor();
fd.etInt$(fileDesc); // 获取zygote socket的文件描述符
return new LocalServerSocket(fd); // 创建Socket的本地服务端
} catch (IOException ex) {
throw new RuntimeException(
"Error building socket from file descriptor: " + fileDesc, ex);
}
}

path: \frameworks\base\core\java\android\net\LocalServerSocket.java

public LocalServerSocket(FileDescriptor fd) throws IOException{ impl = new LocalSocketImpl(fd); impl.listen(LISTEN_BACKLOG); localAddress = impl.getSockAddress(); }

4.2.4 [ZygoteInit.java] forkSystemServer()

private static Runnable forkSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) {
long capabilities = posixCapabilitiesAsBits( OsConstants.CAP_IPC_LOCK, OsConstants.CAP_KILL, OsConstants.CAP_NET_ADMIN, OsConstants.CAP_NET_BIND_SERVICE, OsConstants.CAP_NET_BROADCAST, OsConstants.CAP_NET_RAW, OsConstants.CAP_SYS_MODULE, OsConstants.CAP_SYS_NICE, OsConstants.CAP_SYS_PTRACE, OsConstants.CAP_SYS_TIME, OsConstants.CAP_SYS_TTY_CONFIG, OsConstants.CAP_WAKE_ALARM, OsConstants.CAP_BLOCK_SUSPEND);
......
//参数准备 /* Hardcoded command line to start the system server */ String args[] = { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023," + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010", "--capabilities=" + capabilities + "," + capabilities, "--nice-name=system_server", "--runtime-args", "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT, "com.android.server.SystemServer", };
ZygoteArguments parsedArgs = null; int pid;
try { //将上面准备的参数,按照ZygoteArguments的风格进行封装 parsedArgs = new ZygoteArguments(args); Zygote.applyDebuggerSystemProperty(parsedArgs); Zygote.applyInvokeWithSystemProperty(parsedArgs); boolean profileSystemServer = SystemProperties.getBoolean( "dalvik.vm.profilesystemserver", false); if (profileSystemServer) { parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER; }
//通过fork"分裂"出子进程system_server /* Request to fork the system server process */ pid = Zygote.forkSystemServer( parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids, parsedArgs.mRuntimeFlags, null, parsedArgs.mPermittedCapabilities, parsedArgs.mEffectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); }
//进入子进程system_server /* For child process */ if (pid == 0) { // 处理32_64和64_32的情况 if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); }
// fork时会copy socket,system server需要主动关闭 zygoteServer.closeServerSocket(); // system server进程处理自己的工作 return handleSystemServerProcess(parsedArgs); } return null; }


ZygoteInit。forkSystemServer()会在新fork出的子进程中调用 handleSystemServerProcess(),

主要是返回Runtime.java的MethodAndArgsCaller的方法,然后通过r.run() 启动com.android.server.SystemServer的main 方法

这个当我们后面的SystemServer的章节进行详细讲解。

handleSystemServerProcess代码流程:

handleSystemServerProcess()
|
[ZygoteInit.java]
zygoteInit()
|
[RuntimeInit.java]
applicationInit()
|
findStaticMain()
|
MethodAndArgsCaller()

4.2.5 [ZygoteServer.java] runSelectLoop()

path: frameworks\base\core\java\com\android\internal\os\ZygoteServer.java

Runnable runSelectLoop(String abiList) { ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>(); ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
// 首先将server socket加入到fds socketFDs.add(mZygoteSocket.getFileDescriptor()); peers.add(null);
while (true) { fetchUsapPoolPolicyPropsWithMinInterval();
int[] usapPipeFDs = null; StructPollfd[] pollFDs = null;
// 每次循环,都重新创建需要监听的pollFds // Allocate enough space for the poll structs, taking into account // the state of the USAP pool for this Zygote (could be a // regular Zygote, a WebView Zygote, or an AppZygote). if (mUsapPoolEnabled) { usapPipeFDs = Zygote.getUsapPipeFDs(); pollFDs = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length]; } else { pollFDs = new StructPollfd[socketFDs.size()]; }
/* * For reasons of correctness the USAP pool pipe and event FDs * must be processed before the session and server sockets. This * is to ensure that the USAP pool accounting information is * accurate when handling other requests like API blacklist * exemptions. */
int pollIndex = 0; for (FileDescriptor socketFD : socketFDs) { // 关注事件到来 pollFDs[pollIndex] = new StructPollfd(); pollFDs[pollIndex].fd = socketFD; pollFDs[pollIndex].events = (short) POLLIN; ++pollIndex; }
final int usapPoolEventFDIndex = pollIndex;
if (mUsapPoolEnabled) { pollFDs[pollIndex] = new StructPollfd(); pollFDs[pollIndex].fd = mUsapPoolEventFD; pollFDs[pollIndex].events = (short) POLLIN; ++pollIndex;
for (int usapPipeFD : usapPipeFDs) { FileDescriptor managedFd = new FileDescriptor(); managedFd.setInt$(usapPipeFD);
pollFDs[pollIndex] = new StructPollfd(); pollFDs[pollIndex].fd = managedFd; pollFDs[pollIndex].events = (short) POLLIN; ++pollIndex; } }
try { // 等待事件到来 Os.poll(pollFDs, -1); } catch (ErrnoException ex) { throw new RuntimeException("poll failed", ex); }
boolean usapPoolFDRead = false;
//倒序处理,即优先处理已建立链接的信息,后处理新建链接的请求 while (--pollIndex >= 0) { if ((pollFDs[pollIndex].revents & POLLIN) == 0) { continue; }
// server socket最先加入fds, 因此这里是server socket收到数据 if (pollIndex == 0) { // 收到新的建立通信的请求,建立通信连接 ZygoteConnection newPeer = acceptCommandPeer(abiList); // 加入到peers和fds, 即下一次也开始监听 peers.add(newPeer); socketFDs.add(newPeer.getFileDescriptor());
} else if (pollIndex < usapPoolEventFDIndex) { //说明接收到AMS发送过来创建应用程序的请求,调用processOneCommand //来创建新的应用程序进程 // Session socket accepted from the Zygote server socket try { //有socket连接,创建ZygoteConnection对象,并添加到fds。 ZygoteConnection connection = peers.get(pollIndex); //处理连接,参考[4.2.6] final Runnable command = connection.processOneCommand(this);
// TODO (chriswailes): Is this extra check necessary? if (mIsForkChild) { // We're in the child. We should always have a command to run at this // stage if processOneCommand hasn't called "exec". if (command == null) { throw new IllegalStateException("command == null"); }
return command; } else { // We're in the server - we should never have any commands to run. if (command != null) { throw new IllegalStateException("command != null"); }
// We don't know whether the remote side of the socket was closed or // not until we attempt to read from it from processOneCommand. This // shows up as a regular POLLIN event in our regular processing loop. if (connection.isClosedByPeer()) { connection.closeSocket(); peers.remove(pollIndex); socketFDs.remove(pollIndex); //处理完则从fds中移除该文件描述符 } } } catch (Exception e) { ...... } finally { mIsForkChild = false; } } else { //处理USAP pool的事件 // Either the USAP pool event FD or a USAP reporting pipe.
// If this is the event FD the payload will be the number of USAPs removed. // If this is a reporting pipe FD the payload will be the PID of the USAP // that was just specialized. long messagePayload = -1;
try { byte[] buffer = new byte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES]; int readBytes = Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length);
if (readBytes == Zygote.USAP_MANAGEMENT_MESSAGE_BYTES) { DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(buffer));
messagePayload = inputStream.readLong(); } else { Log.e(TAG, "Incomplete read from USAP management FD of size " + readBytes); continue; } } catch (Exception ex) { if (pollIndex == usapPoolEventFDIndex) { Log.e(TAG, "Failed to read from USAP pool event FD: " + ex.getMessage()); } else { Log.e(TAG, "Failed to read from USAP reporting pipe: " + ex.getMessage()); }
continue; }
if (pollIndex > usapPoolEventFDIndex) { Zygote.removeUsapTableEntry((int) messagePayload); }
usapPoolFDRead = true; } }
// Check to see if the USAP pool needs to be refilled. if (usapPoolFDRead) { int[] sessionSocketRawFDs = socketFDs.subList(1, socketFDs.size()) .stream() .mapToInt(fd -> fd.getInt$()) .toArray();
final Runnable command = fillUsapPool(sessionSocketRawFDs);
if (command != null) { return command; } } } }

4.2.6 [ZygoteConnection.java] processOneCommand()

Runnable processOneCommand(ZygoteServer zygoteServer) { ... //fork子进程 pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids, parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote, parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion); if (pid == 0) { // 子进程执行 zygoteServer.setForkChild(); //进入子进程流程,参考[4.2.7] return handleChildProc(parsedArgs, descriptors, childPipeFd, parsedArgs.mStartChildZygote); } else { //父进程执行 // In the parent. A pid < 0 indicates a failure and will be handled in handleParentProc. handleParentProc(pid, descriptors, serverPipeFd); return null; } ... }

4.2.7 [ZygoteConnection.java] handleChildProc()

private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, boolean isZygote) { ... if (parsedArgs.mInvokeWith != null) { ... throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned"); } else { if (!isZygote) { // App进程将会调用到这里,执行目标类的main()方法 return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mRemainingArgs, null /* classLoader */); } else { return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mRemainingArgs, null /* classLoader */); } } }


这一节主要是讲解Zygote的启动流程,后面会详细讲解Zygote fork子进程的过程

: . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存